package com.dxy.lc.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.dxy.lc.base.AppConstant;
import com.dxy.lc.enums.RoomUserOpt;
import com.dxy.lc.enums.RoomType;
import com.dxy.lc.listener.event.MemberEditEvent;
import com.dxy.lc.manager.DeptCacheManager;
import com.dxy.lc.manager.UserCacheManager;
import com.dxy.lc.model.bean.RoomEditDto;
import com.dxy.lc.model.entity.Dept;
import com.dxy.lc.model.entity.Room;
import com.dxy.lc.mapper.RoomMapper;
import com.dxy.lc.model.entity.RoomUser;
import com.dxy.lc.model.entity.User;
import com.dxy.lc.service.MessageService;
import com.dxy.lc.service.RoomService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dxy.lc.service.RoomUserService;
import com.dxy.lc.socketio.ISessionService;
import com.dxy.lc.utils.EventUtil;
import com.dxy.lc.utils.LoginUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author dxy
 * @since 2024-11-07
 */
@Slf4j
@Service
public class RoomServiceImpl extends ServiceImpl<RoomMapper, Room> implements RoomService {


    @Autowired
    private RoomUserService roomUserService;
    @Autowired
    private MessageService messageService;
    @Autowired
    private ISessionService sessionService;


    /**
     * 只允许编名称和公告
     *
     * @param param
     */
    @Override
    public void updById(RoomEditDto param) {
        Assert.notNull(param.getRoomId());
        String loginUserId = LoginUtil.getLoginUserIdOrException();
        // 不是群成员不能编辑
        Wrapper<RoomUser> wrapper = new LambdaQueryWrapper<RoomUser>()
                .eq(RoomUser::getRoomId, param.getRoomId())
                .eq(RoomUser::getUserId, Integer.parseInt(loginUserId));
        if (roomUserService.count(wrapper) > 0) {
            baseMapper.updateById(new Room().setId(param.getRoomId())
                    .setRoomName(param.getRoomName())
                    .setRoomBulletin(param.getRoomBulletin()));

            if (StrUtil.isNotEmpty(param.getRoomName())){
                Map<String, Object> payload = new HashMap<>();
                payload.put("roomId", param.getRoomId());
                payload.put("roomName", param.getRoomName());
                sessionService.sendMessageByRoomId(param.getRoomId().toString(), AppConstant.SOCKET_EVENT_UPD_GROUP_NAME, payload);
            }
        }

    }

    @Override
    public List<Room> getList(String kw) {
        String loginUserId = LoginUtil.getLoginUserIdOrException();
        List<Room> list = baseMapper.getByUserId(Integer.parseInt(loginUserId));
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }

        // 过滤
        Stream<Room> stream = list.stream()
                .filter(room -> {
                    if (RoomType.PRIVATE.toCode().equals(room.getRoomType().toString())) {
                        User user = baseMapper.getPrivateChatUser(room.getId(), Integer.parseInt(loginUserId));
                        if (user != null) {
                            Dept dept = DeptCacheManager.INSTANCE.getById(user.getDeptId());
                            user.setDeptName(dept != null ? dept.getName() : "");
                            room.setRoomName(user.getUsername()).setRoomAvatar(user.getAvatar());
                            room.setExtData(user);
                            return true;
                        } else {
                            log.warn("房间{}私聊用户不存在", room.getId());
                            return false;
                        }
                    }
                    return true;
                });
        if (StrUtil.isNotEmpty(kw)) {
            stream = stream.filter(room -> room.getRoomName().contains(kw));
        }
        return stream.peek(room -> room.setUnreadMsgCount(messageService.countUnreadMsg(room.getId())))
                .sorted(Comparator.comparing(Room::getLastMsgAt, Comparator.nullsLast(Comparator.naturalOrder())).reversed())
                .collect(Collectors.toList());
    }

    /**
     * 创建聊天室
     *
     * @param toUserIds
     * @return
     */
    @Override
    public Room createRoom(List<Integer> toUserIds) {
        Assert.notEmpty(toUserIds);
        String loginUserId = LoginUtil.getLoginUserIdOrException();
        List<Integer> filteredUserIds = toUserIds.stream()
                .filter(userId -> !loginUserId.equals(userId.toString())).collect(Collectors.toList());
        Assert.notEmpty(filteredUserIds);

        if (filteredUserIds.size() == 1) { // 私聊
            Integer toUserId = toUserIds.get(0);
            return createPrivateChatRoom(toUserId);
        } else { // 群聊
            return createGroupChatRoom(filteredUserIds);
        }
    }

    @Override
    public void addMember(RoomEditDto param) {
        Integer roomId = param.getRoomId();
        Assert.notNull(roomId);
        List<Integer> memberIds = param.getMemberIds();
        Assert.notEmpty(memberIds);
        Room room = baseMapper.selectById(roomId);
        Assert.notNull(room);
        memberIds.forEach(userId -> {
            Wrapper<RoomUser> wrapper = new LambdaQueryWrapper<RoomUser>()
                    .eq(RoomUser::getRoomId, roomId)
                    .eq(RoomUser::getUserId, userId);
            if (roomUserService.count(wrapper) == 0) {
                roomUserService.save(new RoomUser()
                        .setRoomId(roomId)
                        .setUserId(userId));
            }
        });

        // 私聊升级为群聊
        if (RoomType.PRIVATE.toCode().equals(room.getRoomType().toString())) {
            Wrapper<RoomUser> wrapper = new LambdaQueryWrapper<RoomUser>()
                    .eq(RoomUser::getRoomId, roomId);
            if (roomUserService.count(wrapper) > 2) {
                Room entity = new Room()
                        .setId(roomId)
                        .setRoomType(Integer.parseInt(RoomType.GROUP.toCode()))
                        .setRoomName(RandomUtil.randomString(5));
                baseMapper.updateById(entity);
            }
        }

        // 发布事件
        EventUtil.publishEvent(new MemberEditEvent(this, roomId, memberIds.toArray(new Integer[0]), RoomUserOpt.JOIN));
    }


    @Override
    public void setMuted(RoomUser param) {
        Integer roomId = param.getRoomId();
        Integer isMuted = param.getIsMuted();
        Assert.notNull(roomId);
        Assert.notNull(isMuted);
        String loginUserId = LoginUtil.getLoginUserIdOrException();
        roomUserService.update(null, new LambdaUpdateWrapper<RoomUser>()
                .set(RoomUser::getIsMuted, isMuted)
                .eq(RoomUser::getRoomId, roomId)
                .eq(RoomUser::getUserId, Integer.parseInt(loginUserId)));
    }

    @Override
    public void quitRoom(RoomEditDto param) {
        Integer roomId = param.getRoomId();
        Assert.notNull(roomId);
        Integer loginUserId = Integer.parseInt(LoginUtil.getLoginUserIdOrException());
        roomUserService.remove(new LambdaQueryWrapper<RoomUser>()
                .eq(RoomUser::getRoomId, roomId)
                .eq(RoomUser::getUserId, loginUserId));

        // 此处暂不清空聊天记录

        // 发布事件
        Integer[] memberIds = new Integer[]{loginUserId};
        EventUtil.publishEvent(new MemberEditEvent(this, roomId, memberIds, RoomUserOpt.REMOVE));
    }

    @Override
    public List<User> getUsers(Integer roomId) {
        Assert.notNull(roomId);
        return baseMapper.getUsers(roomId);
    }

    @Override
    public Room getDetail(Integer id) {
        Assert.notNull(id);
        Room room = baseMapper.selectById(id);
        Assert.notNull(room);
        String loginUserId = LoginUtil.getLoginUserIdOrException();
        if (RoomType.PRIVATE.toCode().equals(room.getRoomType().toString())) {
            User user = baseMapper.getPrivateChatUser(room.getId(), Integer.parseInt(loginUserId));
            if (user != null) {
                Dept dept = DeptCacheManager.INSTANCE.getById(user.getDeptId());
                user.setDeptName(dept != null ? dept.getName() : "");
                room.setRoomName(user.getUsername()).setRoomAvatar(user.getAvatar());
                room.setExtData(user);
            }
        }
        RoomUser ru = roomUserService.getOne(new LambdaQueryWrapper<RoomUser>()
                .eq(RoomUser::getRoomId, id)
                .eq(RoomUser::getUserId, Integer.parseInt(loginUserId)));
        room.setIsMuted(ru.getIsMuted());
        room.setUnreadMsgCount(messageService.countUnreadMsg(room.getId()));
        return room;
    }

    /**
     * 创建私聊聊天室
     *
     * @param toUserId
     * @return
     */
    private Room createPrivateChatRoom(Integer toUserId) {
        String loginUserId = LoginUtil.getLoginUserIdOrException();
        Room room = baseMapper.getPrivateChatRoom(Integer.parseInt(loginUserId), toUserId);
        if (room == null) { // 未存在聊天室则创建
            room = new Room().setRoomType(Integer.parseInt(RoomType.PRIVATE.toCode()));
            baseMapper.insert(room);
            List<RoomUser> list = Arrays.asList(
                    new RoomUser().setRoomId(room.getId()).setUserId(toUserId),
                    new RoomUser().setRoomId(room.getId()).setUserId(Integer.parseInt(loginUserId))
            );
            roomUserService.saveBatch(list);

            // 发布聊天室创建事件绑定session
            EventUtil.publishEvent(new MemberEditEvent(this,
                    room.getId(),
                    ArrayUtil.wrap(toUserId, Integer.parseInt(loginUserId)),
                    RoomUserOpt.JOIN));
        }

        User user = UserCacheManager.INSTANCE.getById(toUserId);
        Dept dept = DeptCacheManager.INSTANCE.getById(user.getDeptId());
        user.setDeptName(dept != null ? dept.getName() : "");
        room.setRoomName(user.getUsername());
        room.setRoomAvatar(user.getAvatar());
        room.setExtData(user);
        return room;
    }

    /**
     * 创建群聊聊天室
     *
     * @param memberUserIds
     * @return
     */
    private Room createGroupChatRoom(List<Integer> memberUserIds) {
        String loginUserId = LoginUtil.getLoginUserIdOrException();
        Room room = new Room()
                .setRoomType(Integer.parseInt(RoomType.GROUP.toCode()))
                .setRoomName("群组" + RandomUtil.randomString(5));
        baseMapper.insert(room);
        List<RoomUser> list = new ArrayList<>();
        for (Integer toUserId : memberUserIds) {
            if (loginUserId.equals(toUserId.toString())) {
                continue;
            }
            list.add(new RoomUser().setRoomId(room.getId()).setUserId(toUserId));
        }
        list.add(new RoomUser()
                .setRoomId(room.getId())
                .setUserId(Integer.parseInt(loginUserId)));
        roomUserService.saveBatch(list);

        // 发布聊天室创建事件绑定session
        Integer[] userIds = list.stream().map(RoomUser::getUserId).toArray(Integer[]::new);
        EventUtil.publishEvent(new MemberEditEvent(this, room.getId(), userIds, RoomUserOpt.JOIN));
        return room;
    }

}
